package com.tqz.juc.queue;

import lombok.SneakyThrows;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * <p>阻塞队列
 *
 * @author tianqingzhao
 * @since 2022/1/31 10:45
 */
public class BlackQueueTest {
    
    static BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
    
    public static void main(String[] args) {
        new Thread(new Producer(), "producer").start();
        new Thread(new Consumer(), "consumer").start();
    }
    
    static class Producer extends Thread {
        
        @SneakyThrows
        @Override
        public void run() {
            for (int i = 1; ; i++) {
                // add()、offer()、put() 都是向队列中添加一个元素。
                // 但是如果想在一个满的队列中加入一个新元素，
                // 1.add()：方法就会抛出一个java.lang.IllegalStateException: Queue full 异常，
                // 2.offer()：方法会返回 false
                // 3.put()：方法阻塞，直到能够有空间插入元素
                queue.offer(String.valueOf(i));
                
                Thread.sleep(2000);
                
                if (i == 10) {
                    break;
                }
            }
        }
    }
    
    static class Consumer extends Thread {
        
        @Override
        public void run() {
            try {
                for (; ; ) {
                    // take()、poll()、remove()、peek()、element()、queue.drainTo()的区别
                    // 1.take()：若队列为空，发生阻塞，等待有元素。
                    // 2.poll()和remove()的区别：poll()和remove()都将移除并且返回队头，但是在poll()在队列为空时返回null，
                    // 而remove()会抛出NoSuchElementException异常。
                    // 3：peek()和element()：都将在不移除的情况下返回队头，但是peek()方法在队列为空时返回null，
                    // 调用element()方法会抛出NoSuchElementException异常。
                    // 4.drainTo()：一次性从BlockingQueue获取所有可用的数据对象（还可以指定获取数据的个数），
                    //　通过该方法，可以提升获取数据效率；不需要多次分批加锁或释放锁。
                    String message = queue.take();
                    System.out.println(message);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
